package com.fingard.dsp.bank.directbank.tzb01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.util.SmbFileUtil;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * Created by aaron on 2020/4/28.
 */
public class TZB01ReceiptPro extends TZB01Base implements IReceiptPro {
    @Override
    public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        //下载回单信息
        ReceiptDataHelper receiptHelper = null;//回单数据保存类，分区分表
        try {
            receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);
            String qryDateStr = Format.Date8Format.format(pOneDay);
            //查询回单信息文件
            String fileName = qryReceiptInfo(pConfig, pReqReceipt, qryDateStr);

            //解析回单信息文件
            if (StringHelper.hasAnyChar(fileName)) {
                parseInfoFile(receiptHelper, pReqReceipt, fileName, qryDateStr);
            }
            //下载回单图片
            downPdfFile(pConfig, receiptHelper, pReqReceipt.actNum, qryDateStr);
        }catch (Exception ex){
            ex.printStackTrace();
            WriteBankLogLn(ex.getMessage());
            FGBiz.logTrace.error(this.getLogCode(),ex.getMessage());
        }finally {
            if(receiptHelper!=null) {
                receiptHelper.close();
            }
        }
        return null;
    }

    /**
     * 下载信息文件
     *
     * @param p_reqReceipt
     * @param qryDateStr
     * @return
     */
    private String qryReceiptInfo(ReceiptProConfig pConfig,ReqQryReceipt p_reqReceipt,String qryDateStr) {
        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            TZB01Header header = new TZB01Header();
            header.tr_code = "544003";
            header.req_no = p_reqReceipt.reqHeader.reqSeqID;
            writeCommonHeader(xmlWriter, header);
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("body");
            // 1	acno	账号	C20	M
            xmlWriter.writeElementString("acno", p_reqReceipt.actNum);
//                 2	start_date	开始日期	C8	M
            xmlWriter.writeElementString("start_date", "" + qryDateStr);
//                 3	end_date	结束日期	C8	M
            xmlWriter.writeElementString("end_date", "" + qryDateStr);
            xmlWriter.writeEndDocument();
            //拼接报文, 统计字节长度
            int length = xmlWriter.toXmlString().getBytes(getCharset()).length + 2;
            String head = String.format("%-10s", length + "") + "00";
            String aLog =head + xmlWriter.toXmlString();
            FGBiz.logTrace.info(this.getLogCode(),"发送银行的报文：\r\n"+aLog);
            String[] bankResult = sendToBank(aLog);
            FGBiz.logTrace.info(this.getLogCode(),"银行返回的报文：\r\n"+bankResult[1]);
            if (bankResult[0].length() == 0) {
                StringBuilder tmpBkMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(bankResult[1].substring(12), tmpBkMsg);
                if (tmpBkReader != null) {
                    String succFlag = tmpBkReader.getFirstText("/ap/head/succ_flag");
                    String retCode = tmpBkReader.getFirstText("/ap/head/ret_code");
                    String retInfo = tmpBkReader.getFirstText("/ap/head/ret_info");
                    if (succFlag.equals("0") && retCode.equals("0000")) {
                        String fileName = tmpBkReader.getFirstText("/ap/body/file_name");
                        if (StringHelper.hasAnyChar(fileName)) {
                            String receiptDownType = getBankConfig().getValueAsString("receiptDownType");
                            //回单信息目录
                            String receiptInfoDir = pConfig.getSaveSubDir(reqHeader,Format.Date8Format.parse(qryDateStr)) + File.separator +"tmpdir"+ File.separator +
                                    p_reqReceipt.actNum+File.separator + qryDateStr+File.separator+"dataInfo";
                            boolean downflag = downFileToLocal(receiptDownType,receiptInfoDir,fileName);
                            if(downflag) {
                                return receiptInfoDir + File.separator + fileName;
                            }
                        } else {
                            aLog =tmpBkReader.getFirstText("/ap/head/ext_info");
                            WriteBankLogLn(aLog);
                            FGBiz.logTrace.info(this.getLogCode(),aLog);
                        }
                    } else {
                        WriteBankLogLn(retInfo);
                        FGBiz.logTrace.info(this.getLogCode(),retInfo);
                    }
                } else {
                    WriteBankLogLn(tmpBkMsg.toString());
                    FGBiz.logTrace.info(this.getLogCode(),tmpBkMsg.toString());
                }
            } else {
                WriteBankLogLn(bankResult[1]);
                FGBiz.logTrace.info(this.getLogCode(),bankResult[1]);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            WriteBankLogLn(ex.getMessage());
            FGBiz.logTrace.error(this.getLogCode(),ex.getMessage());
        }
        return "";
    }

    /**
     * 解析回单信息
     *
     * @param receiptHelper
     * @param p_reqReceipt
     * @param filename
     * @param qryDateStr
     * @return
     */
    private void parseInfoFile(ReceiptDataHelper receiptHelper, ReqQryReceipt p_reqReceipt, String filename, String qryDateStr) throws Exception{

        String aLog;
        String receiptdatetxt = FileHelper.readFileText(filename, getCharset());
        String[] receiptInfoList = receiptdatetxt.split("\\n");
        //key为日期_账号
        if (receiptInfoList != null && receiptInfoList.length != 0) {
            for (String receiptInfoStr : receiptInfoList) {
                //0交易单号|1经办日期|2账号|3原交易流水号|4交易金额|5经办柜员|
                String[] receiptInfo = receiptInfoStr.split("\\|");
                ReceiptData rcpt = new ReceiptData();
                rcpt.bank = "20090";
                rcpt.srcSys = this.bankFront.bankCode;
                rcpt.ownAct = p_reqReceipt.actNum;
                rcpt.istNbr = receiptInfo[0];//回单编号
                rcpt.receiptNo = rcpt.istNbr;
                rcpt.busRef = receiptInfo[3];
                rcpt.busDate = Integer.parseInt(receiptInfo[1]);

                if (!qryDateStr.equals(receiptInfo[1])) {
                    aLog = rcpt.receiptNo + "回单数据的日期" + receiptInfo[1] + "与预期" + qryDateStr + "不符";
                    WriteBankLogLn(aLog);
                    FGBiz.logTrace.error(this.getLogCode(), aLog);
                }

                rcpt.cur = p_reqReceipt.actCur;
                rcpt.busRef3 = "";
                rcpt.moneyWay = "";

                rcpt.amount = new BigDecimal(receiptInfo[4]);
                int inRe = receiptHelper.insertIfNotExist(rcpt);
                if (inRe == 0) {
                    aLog = "回单编号:" + rcpt.istNbr + "写入数据库，影响行数：" + inRe;
                    WriteBankLogLn(aLog);
                    FGBiz.logTrace.info(this.getLogCode(), aLog);
                } else if (inRe == 1) {
                    aLog = "回单编号:" + rcpt.istNbr + "更新数据库，影响行数：" + inRe;
                    WriteBankLogLn(aLog);
                    FGBiz.logTrace.info(this.getLogCode(), aLog);
                }

            }
        }
    }

    /**
     * 下载回单图片
     * @param pConfig
     * @param receiptHelper
     * @param actNum
     * @param qryDateStr
     */
    private void downPdfFile(ReceiptProConfig pConfig,ReceiptDataHelper receiptHelper, String actNum,String qryDateStr){
        String aLog="";
        try {
            //获取文件没有下载成功的文件
            List<String> istNbrList = receiptHelper.getIstNbrList(actNum,Format.Date8Format.parse(qryDateStr));
            for(String istNbr:istNbrList) {
                ReceiptData receiptData = receiptHelper.loadFromDbByIstNbr(actNum, istNbr);
                Date tranDate = Format.Date8Format.parse(receiptData.busDate + "");

                XmlTextWriter xmlWriter = new XmlTextWriter();
                TZB01Header header = new TZB01Header();
                header.req_no = reqHeader.reqSeqID;
                header.tr_code = "544004";
                writeCommonHeader(xmlWriter, header);
                xmlWriter.writeEndElement();
                xmlWriter.writeStartElement("body");
                xmlWriter.writeElementString("tran_receipt_no", istNbr);
                xmlWriter.writeEndDocument();
                int length = xmlWriter.toXmlString().getBytes(getCharset()).length + 2;
                String head = String.format("%-10s", length + "") + "00";
                aLog = head + xmlWriter.toXmlString();
                FGBiz.logTrace.info(this.getLogCode(),"请求银行的报文:\r\n" ,aLog);
                String[] bankResult =sendToBank(aLog);;
                FGBiz.logTrace.info(this.getLogCode(), "银行返回的报文:\r\n",bankResult[1]);

                if (bankResult[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpbkReader = loadBankRespXmlReader(bankResult[1].substring(12), tmpSbMsg);
                    if (tmpbkReader != null) {
                        String succFlag = tmpbkReader.getFirstText("/ap/head/succ_flag");
                        String retCode = tmpbkReader.getFirstText("/ap/head/ret_code");
                        String retInfo = tmpbkReader.getFirstText("/ap/head/ret_info");
                        if ("0".equals(succFlag) && "0000".equals(retCode)) {
                            String receipt_name = tmpbkReader.getFirstText("/ap/body/file_name");

                            String localDirRelative = pConfig.getRelativeSaveDir(reqHeader, tranDate) + File.separator + actNum;
                            localDirRelative += File.separator + Format.Date10Format.format(tranDate);

                            String localFileRelative = localDirRelative + File.separator + StringHelper.trimStartFileSp(receipt_name);
                            localFileRelative = StringHelper.replaceFileSp(localFileRelative);

                            String localFileReal = pConfig.localSaveMainDir + File.separator + localFileRelative;
                            String receiptDownType = getBankConfig().getValueAsString("receiptDownType");
                            //下载回单文件
                            downFileToLocal(receiptDownType,pConfig.localSaveMainDir + File.separator + localDirRelative,receipt_name);
                            if (FileHelper.existFile(localFileReal)) {
                                int rowAff = receiptHelper.updateDownState(actNum, receiptData.istNbr, localFileRelative, receipt_name, "2");
                                aLog = "回单编号" + receiptData.istNbr + "，文件" + receipt_name + "下载成功，更新影响行数：" + rowAff;
                                aLog = aLog + "\r\n文件保存地址：" + localFileReal;
                                WriteBankLogLn(aLog);
                                FGBiz.logTrace.info(this.getLogCode(), aLog);
                            } else {
                                int rowAff = receiptHelper.updateDownState(actNum, receiptData.istNbr, "", "", "3");
                                aLog = "回单编号" + receiptData.istNbr + "，文件" + receipt_name + "下载失败";
                                WriteBankLogLn(aLog);
                                FGBiz.logTrace.error(this.getLogCode(), aLog);
                            }
                        } else {
                            int rowAff = receiptHelper.updateDownState(actNum, receiptData.istNbr, "", "", "3");
                            aLog = "回单编号：" + receiptData.istNbr + "对于的回单文件下载失败：" + retInfo;
                            WriteBankLogLn(aLog);
                            FGBiz.logTrace.error(this.getLogCode(), aLog);
                        }
                    } else {
                        aLog = "回单编号：" + receiptData.istNbr + "对于的回单文件下载失败：" + tmpSbMsg.toString();
                        WriteBankLogLn(aLog);
                        FGBiz.logTrace.error(this.getLogCode(), aLog);
                    }
                } else {
                    aLog = "回单编号：" + receiptData.istNbr + "对于的回单文件下载失败：" + bankResult[1];
                    WriteBankLogLn(aLog);
                    FGBiz.logTrace.error(this.getLogCode(), aLog);
                }
            }

        }catch (Exception ex){
            ex.printStackTrace();
            WriteBankLogLn(ex.getMessage());
            FGBiz.logTrace.error(this.getLogCode(), ex.getMessage());
        }
    }

    /**
     * 下载制定文件到本地
     * @param receiptDownType
     * @param localSaveDirPath
     * @param fileName
     * @throws Exception
     */
    private boolean downFileToLocal(String receiptDownType,String localSaveDirPath,String fileName)throws Exception{
        String logStr ="";
        if ("sftp".equals(receiptDownType)) {
            //Sftp方式
            SftpPortClient sftpPortClient = null;
            try {
                FtpSet ftpSet = bankFront.getFtpSet("receipt");
                ftpSet.downDir = StringHelper.trimEnd(ftpSet.downDir, "/") + "/";
                logStr ="SFTP下载地址" + ftpSet.serverIP + ":" + ftpSet.port;
                WriteBankLogLn(logStr);
                FGBiz.logTrace.info(this.getLogCode(),logStr);
                sftpPortClient = new SftpPortClient(ftpSet);

                logStr="下载到本地目录为：" + localSaveDirPath;
                WriteBankLogLn(logStr);
                FGBiz.logTrace.info(this.getLogCode(),logStr);

                logStr= "sftp目录下文件名为：" + fileName;
                WriteBankLogLn(logStr);
                FGBiz.logTrace.info(this.getLogCode(),logStr);

                FtpReceiver ftpReceiver = sftpPortClient.downloadFileByName("", localSaveDirPath, fileName);
                if (ftpReceiver.isCompleted) {
                    logStr= "下载成功，下载路径为：" + localSaveDirPath + "文件名为" + fileName;
                    WriteBankLogLn(logStr);
                    FGBiz.logTrace.info(this.getLogCode(),logStr);
                    return true;
                } else {
                    logStr= "下载失败，文件名为" + fileName;
                    WriteBankLogLn(logStr);
                    FGBiz.logTrace.info(this.getLogCode(),logStr);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                WriteBankLogLn(ex);
                FGBiz.logTrace.info(this.getLogCode(),ex.getMessage());
            } finally {
                if (sftpPortClient != null) {
                    sftpPortClient.disconnect();
                }
            }
        } else if ("ftp".equals(receiptDownType)) {
            FtpSet ftpSet = bankFront.getFtpSet("receipt");
            FtpPortClient client = new FtpPortClient(ftpSet);
            FtpReceiver ftpReceiver = client.downloadFileFromDir("",fileName, localSaveDirPath+File.separator+fileName);
            if (!ftpReceiver.isCompleted) {
                WriteBankLogLn(ftpReceiver.connMsg);
                FGBiz.logTrace.info(this.getLogCode(),ftpReceiver.connMsg);
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                logStr= "下载失败";
                WriteBankLogLn(logStr);
                FGBiz.logTrace.info(this.getLogCode(),logStr);
            } else {
                logStr= "下载成功";
                WriteBankLogLn(logStr);
                FGBiz.logTrace.info(this.getLogCode(),logStr);
                return true;
            }
        } else {
            //共享目录方式
            if (StringHelper.hasAnyChar(bankFront.bankReceiptMainDir)) {
                if(bankFront.bankReceiptMainDir.startsWith("smb:")) {
                    StringBuilder smbSb = new StringBuilder();
                    SmbFileUtil.smbDownload(localSaveDirPath, bankFront.bankReceiptMainDir, fileName, smbSb);
                    return true;
                }else {
                    String sourceFilePath = bankFront.bankReceiptMainDir+File.separator+fileName;
                    if(FileHelper.existFile(sourceFilePath)){
                        FileHelper.copyFile(sourceFilePath,localSaveDirPath+File.separator+fileName);
                        return true;
                    }else{
                        logStr = String.format("回单文件不存在【%s】",sourceFilePath);
                        WriteBankLogLn(logStr);
                        FGBiz.logTrace.error(this.getLogCode(),logStr);
                    }
                }
            } else {
                throw new Exception("请配置银行前置机回单目录");
            }
        }
        return false;
    }

}